package com.duck.duckchatbackend.aspect;


import com.duck.duckchatbackend.annotation.GlobalInterceptor;
import com.duck.duckchatbackend.entity.constans.Constants;
import com.duck.duckchatbackend.entity.dto.TokenUserInfoDto;
import com.duck.duckchatbackend.entity.enums.ResponseCodeEnum;
import com.duck.duckchatbackend.exception.BusinessException;
import com.duck.duckchatbackend.redis.RedisUtils;
import com.duck.duckchatbackend.utils.StringTools;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.RequestContext;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;



@Aspect
@Component("operationAspect")
public class GlobalOperationAspect {
    @Resource
    private RedisUtils redisUtils;
    private static final Logger logger = LoggerFactory.getLogger(GlobalOperationAspect.class);

    /**
     * 在执行带有@GlobalInterceptor注解的方法之前，执行此方法进行拦截处理
     * 主要用于全局的登录和权限校验
     *
     * @param point 切入点对象，包含被拦截的方法的信息
     */
    @Before("@annotation(com.duck.duckchatbackend.annotation.GlobalInterceptor)")
    public void interceptorDo(JoinPoint point) {
        try {
            // 获取被拦截方法的签名
            Method method = ((MethodSignature) point.getSignature()).getMethod();
            // 获取2
            GlobalInterceptor interceptor = method.getAnnotation(GlobalInterceptor.class);
            if (interceptor == null) {
                // 如果没有找到注解，则直接返回，不进行拦截处理
                return;
            }
            // 检查是否需要进行登录或管理员权限校验
            if (interceptor.checkLogin() || interceptor.checkAdmin()) {
                // 执行登录或管理员权限校验
                checkLogin(interceptor.checkAdmin());
            }
        } catch (BusinessException e) {
            // 捕获业务异常，并记录日志
            logger.error("全局拦截器异常", e);
            throw e;
        } catch (Exception e) {
            // 捕获其他异常，并记录日志，抛出业务异常
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        } catch (Throwable e) {
            // 捕获Throwable异常，并记录日志，抛出业务异常
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        }
    }

    /**
     * 检查用户登录状态和管理员权限
     *
     * @param checkAdmin 是否需要检查管理员权限
     * @throws BusinessException 如果未登录或需要管理员权限但不是管理员，则抛出业务异常
     */
    private void checkLogin(Boolean checkAdmin) {
        // 获取当前请求的属性
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 获取请求头中的token
        String token = request.getHeader("token");
        if (StringTools.isEmpty(token)) {
            // 如果token为空，则抛出未登录的业务异常
            throw new BusinessException(ResponseCodeEnum.CODE_901);
        }
        // 从Redis中获取token对应的信息
        TokenUserInfoDto tokenUserInfoDto = (TokenUserInfoDto) redisUtils.get(Constants.REDIS_KEY_WS_TOKEN + token);
        if (checkAdmin && !tokenUserInfoDto.getAdmin()) {
            // 如果需要管理员权限但用户不是管理员，则抛出权限不足的业务异常
            throw new BusinessException(ResponseCodeEnum.CODE_404);
        }
    }
}
